package cn.kimmking.research.qedis.core.opr;

import cn.kimmking.research.qedis.core.AbstractOperator;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static java.lang.Math.min;

/**
 * list operators.
 *
 * @Author : kimmking(kimmking@apache.org)
 * @create 2024/6/11 下午8:04
 */
public class ListOperator extends AbstractOperator {

    public int lpush(String key, String... values) {
        CacheEntry<?> entry = getOrInitCacheEntry(key);
        LinkedList<String> exist = (LinkedList<String>) entry.getValue();
        Arrays.stream(values).forEach(exist::addFirst);
        return values.length;
    }

    public int rpush(String key, String... values) {
        CacheEntry<?> entry = getOrInitCacheEntry(key);
        LinkedList<String> exist = (LinkedList<String>) entry.getValue();
        exist.addAll(List.of(values));
        return values.length;
    }

    public String[] lpop(String key, int count) {
        if(checkInvalid(key)) return null;
        LinkedList<String> v = (LinkedList<String>) getEntryValue(key);
        int len = min(count, v.size());
        String[] ret = new String[len];
        int index = 0;
        while (index < len) {
            ret[index ++] = v.removeFirst();
        }
        return ret;
    }

    public String[] rpop(String key, int count) {
        if(checkInvalid(key)) return null;
        LinkedList<String> v = (LinkedList<String>) getEntryValue(key);
        int len = min(count, v.size());
        String[] ret = new String[len];
        int index = 0;
        while (index < len) {
            ret[index ++] = v.removeLast();
        }
        return ret;
    }

    public int llen(String key) {
        if(checkInvalid(key)) return 0;
        LinkedList<String> v = (LinkedList<String>) getEntryValue(key);
        return v.size();
    }

    public String[] lrange(String key, int start, int stop) {
        if(checkInvalid(key)) return new String[0];
        LinkedList<String> v = (LinkedList<String>) getEntryValue(key);
        int size = v.size();
        int len = min(size-start, stop-start+1);
        String[] ret = new String[len];
        for(int i = 0; i < len; i ++) {
            ret[i] = v.get(start + i);
        }
        return ret;
    }

    public String lindex(String key, int index) {
        if(checkInvalid(key)) return null;
        LinkedList<String> v = (LinkedList<String>) getEntryValue(key);
        if(index >= v.size()) return null;
        return v.get(index);
    }

    private CacheEntry<?> getOrInitCacheEntry(String key) {
        CacheEntry<?> entry = getEntry(key);
        if(entry == null) {
            synchronized (getMap()) {
                if((entry = getEntry(key)) == null) {
                    entry = new CacheEntry<>(new LinkedList<String>(), System.currentTimeMillis(), -1000);
                    putEntry(key, entry);
                }
            }
        }
        return entry;
    }

}
